'use strict';

module.exports = exec;

const CACHE_DIR = "dependencies";

const settings = {
  init: '@duo-cli/init'
}

const cp = require('child_process');
const Package = require("@duo-cli/package");
const log = require("@duo-cli/log");
const path = require('path');

async function exec() {
  let targetPath = process.env.CLI_TARGET_PATH;
  log.verbose('命令行输入的targetPath:', targetPath);

  let storeDir = "";
  const cmdObj = arguments[arguments.length - 1];
  const cmdName = cmdObj.name();
  const packageName = settings[cmdName];
  const packageVersion = 'latest';
  let pkg;
  if (!targetPath) {
    targetPath = path.resolve(process.env.CLI_HOME_PATH, CACHE_DIR);
    storeDir = path.resolve(targetPath, 'node_modules');
    log.verbose('默认的targetPath:', targetPath);
    log.verbose('默认的storeDir:', storeDir);

    pkg = new Package({
      targetPath,
      storeDir,
      packageName,
      packageVersion
    });
    if (await pkg.exists()) {
      // 更新package
      log.verbose('更新package>');
      pkg.update();
    } else {
      // 安装package
      log.verbose('安装package>');
      await pkg.install();
    }
  } else {
    pkg = new Package({
      targetPath,
      packageName,
      packageVersion
    });
  }
  const rootFile = pkg.getRootFilePath();
  log.verbose('rootFile>', rootFile);
  if (rootFile) {
    try {
      const args = Array.from(arguments);
      const cmd = args[args.length - 1];
      // 过滤最后一个参数中带下划线和parent参数，以及原型链上的数据
      const o = Object.create(null);
      Object.keys(cmd).forEach(key => {
        if (cmd.hasOwnProperty(key) && !key.startsWith('_') && key !== 'parent') {
          o[key] = cmd[key]
        }
      })
      args[args.length - 1] = o;
      const code = `require('${rootFile}').call(null, ${JSON.stringify(args)})`;
      const child = spawn('node', ['-e', code], {
        cwd: process.cwd(),
        stdio: 'inherit'
        //stdio：默认pipe,创建子进程之后，子和父就会建立一个通道
      });
      child.on('error', e => {
        log.error(e.message);
        process.exit(1);
      })
      child.on('exit', e => {
        log.verbose("exec_exit>>", e)
        process.exit(e);
      })
    }  catch (error) {
      log.error(error.message)
    }
  }
}

function spawn(command, args, options) {
    const win32 = process.platform === 'win32'
    const cmd = win32 ? 'cmd' : command
    const cmdArgs = win32 ? ['/c'].concat(command, args) : args
    //在windows下可能是这样执行spawn的
    //cp.spawn('cmd',['/c','node','-e',code])
    //cmd是用来执行的主参数，-c表示静默执行
    return cp.spawn(cmd, cmdArgs, options || {})
}
